(四)Android基于UDP的多客户端语音通信

您所在的位置:网站首页 Android 语音聊天监听 (四)Android基于UDP的多客户端语音通信

(四)Android基于UDP的多客户端语音通信

2024-07-16 13:37| 来源: 网络整理| 查看: 265

转载请表明出处:https://blog.csdn.net/stormxiaofeng/article/details/80598126

在前三篇得基础上,这次研究了组播功能。非常感谢https://blog.csdn.net/jspping/article/details/64438515得贡献!

组播也就是通过MulticastSocket来进行开发,与DatagramSocket比较相类似,这次依然是用两个线程进行实现,发送线程MultiSendThread和接收线程MultiReceiveThread。废话不多说,开始码:

(一)MultiSendThread:

(1)初始化MuticastSocket

  // 侦听的端口 try { multicastSocket = new MulticastSocket(8082); // 使用D类地址,该地址为发起组播的那个ip段,即侦听10001的套接字 address = InetAddress.getByName("239.0.0.1"); } catch (IOException e) { e.printStackTrace(); }

(2)初始化AudioRecord

protected LinkedList mRecordQueue; int minBufferSize; private static AcousticEchoCanceler aec; private static AutomaticGainControl agc; private static NoiseSuppressor nc; AudioRecord audioRec; byte[] buffer; @RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN) private void initAudio() { //播放的采样频率 和录制的采样频率一样 int sampleRate = 44100; //和录制的一样的 int audioFormat = AudioFormat.ENCODING_PCM_16BIT; //录音用输入单声道 播放用输出单声道 int channelConfig = AudioFormat.CHANNEL_IN_MONO; minBufferSize = AudioRecord.getMinBufferSize( sampleRate, channelConfig, AudioFormat.ENCODING_PCM_16BIT); System.out.println("****RecordMinBufferSize = " + minBufferSize); audioRec = new AudioRecord( MediaRecorder.AudioSource.MIC, sampleRate, channelConfig, audioFormat, minBufferSize); buffer = new byte[minBufferSize]; if (audioRec == null) { return; } //声学回声消除器 AcousticEchoCanceler 消除了从远程捕捉到音频信号上的信号的作用 if (AcousticEchoCanceler.isAvailable()) { aec = AcousticEchoCanceler.create(audioRec.getAudioSessionId()); if (aec != null) { aec.setEnabled(true); } } //自动增益控制 AutomaticGainControl 自动恢复正常捕获的信号输出 if (AutomaticGainControl.isAvailable()) { agc = AutomaticGainControl.create(audioRec.getAudioSessionId()); if (agc != null) { agc.setEnabled(true); } } //噪声抑制器 NoiseSuppressor 可以消除被捕获信号的背景噪音 if (NoiseSuppressor.isAvailable()) { nc = NoiseSuppressor.create(audioRec.getAudioSessionId()); if (nc != null) { nc.setEnabled(true); } } mRecordQueue = new LinkedList(); }

(3)开始录制,并实时发送出去

@Override public void run() { if (multicastSocket == null) return; try { audioRec.startRecording(); while (true) { try { byte[] bytes_pkg = buffer.clone(); if (mRecordQueue.size() >= 2) { int length = audioRec.read(buffer, 0, minBufferSize); // 组报 DatagramPacket datagramPacket = new DatagramPacket(buffer, length); // 向组播ID,即接收group /239.0.0.1 端口 10001 datagramPacket.setAddress(address); // 发送的端口号 datagramPacket.setPort(10001); System.out.println("AudioRTwritePacket = " + datagramPacket.getData().toString()); multicastSocket.send(datagramPacket); } mRecordQueue.add(bytes_pkg); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } } } catch (Exception e) { e.printStackTrace(); } }

(二)MultiReceiveThread

(1)初始化MulticastSocket

// 接收数据时需要指定监听的端口号 try { multicastSocket = new MulticastSocket(10001); // 创建组播ID地址 InetAddress address = InetAddress.getByName("239.0.0.1"); // 加入地址 multicastSocket.joinGroup(address); } catch (IOException e) { e.printStackTrace(); }

(2)初始化AudioTrack

byte[] buffer; AudioTrack audioTrk; private void initAudioTracker() { //扬声器播放 int streamType = AudioManager.STREAM_MUSIC; //播放的采样频率 和录制的采样频率一样 int sampleRate = 44100; //和录制的一样的 int audioFormat = AudioFormat.ENCODING_PCM_16BIT; //流模式 int mode = AudioTrack.MODE_STREAM; //录音用输入单声道 播放用输出单声道 int channelConfig = AudioFormat.CHANNEL_OUT_MONO; int recBufSize = AudioTrack.getMinBufferSize( sampleRate, channelConfig, audioFormat); System.out.println("****playRecBufSize = " + recBufSize); audioTrk = new AudioTrack( streamType, sampleRate, channelConfig, audioFormat, recBufSize, mode); audioTrk.setStereoVolume(AudioTrack.getMaxVolume(), AudioTrack.getMaxVolume()); buffer = new byte[recBufSize]; }

(3)开始接收,并进行实时播放

@Override public void run() { if (multicastSocket == null) return; //从文件流读数据 audioTrk.play(); // 包长 while (true) { try { // 数据报 DatagramPacket datagramPacket = new DatagramPacket(buffer, buffer.length); // 接收数据,同样会进入阻塞状态 multicastSocket.receive(datagramPacket); audioTrk.write(datagramPacket.getData(), 0, datagramPacket.getLength()); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } }

(三)开始测试

MultiSendThread multiSendThread; MultiReceiverThread multiReceiverThread; @OnClick({R.id.btnSend, R.id.btnReceive}) public void onViewClicked(View view) { switch (view.getId()) { case R.id.btnSend: if (multiSendThread == null) { multiSendThread = new MultiSendThread(); } new Thread(multiSendThread).start(); break; case R.id.btnReceive: if (multiReceiverThread == null) { multiReceiverThread = new MultiReceiverThread(); } new Thread(multiReceiverThread).start(); break; } }



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3